package com.example.testsbjenkins.jucTest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author: lt
 * @date: 2022/7/7 17:02
 * @Description: TestCountDownLatch 底层实现原理:基于AQS的共享锁来进行线程的通知,利用cas来进行 count限制的-1
 * CountDownLatch类似于10人找了一个代购，代购收齐了10个客户的钱才买票出国购物，
 * 而CyclicBarrier类似10个拼团购物，人齐了之后开团了，这10个自己买自己的
 */
public class TestCountDownLatch {


    /**
     * 测试 一个线程等待其他多个线程都执行完毕，再继续自己的工作
     */
    static void test1() throws InterruptedException {
        int count =5 ;
        CountDownLatch countDownLatch = new CountDownLatch(count);
        ExecutorService executorService = Executors.newFixedThreadPool(count);
        for (int i = 0; i < count; i++) {
            int no = i+1;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        double v = Math.random() * 1000;
                        Thread.sleep((long) (v));
                        System.out.println(no + "号运动员完成了比赛,耗时:"+v);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        countDownLatch.countDown();
                    }
                }
            };
            executorService.submit(runnable);
        }

        
        

        System.out.println("等待5个运动员都跑完....");
        countDownLatch.await();
        System.out.println("所有人都跑完了,运动结束");
        executorService.shutdown();
    }

    /**
     * 测试 多个线程等待某一个线程的信号，同时开始执行
     */
    static void test2() throws InterruptedException {
        System.out.println("运动员有5秒的准备时间");
        int count = 5;
        CountDownLatch countDownLatch = new CountDownLatch(1);
        ExecutorService executorService = Executors.newFixedThreadPool(count);
        for (int i = 0; i < count; i++) {
            int no = i + 1;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println(no + "号运动员已经准备好,等待发令枪响...." );
                    try {
                        countDownLatch.await();
                        System.out.println(no + "号运动员完成比赛..." );
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } 
                }
            };
            executorService.submit(runnable);
        }
        Thread.sleep(5000);
        System.out.println("5秒准备时间已过，发令枪响，比赛开始！");
        countDownLatch.countDown();
        executorService.shutdown();
    }
    
    //组合多个countDownLatch 完成复杂业务
    static void test3() throws InterruptedException {
        System.out.println("运动员有5秒的准备时间,老师需要等待所有运动员都完成比赛才能下班");
        CountDownLatch latch1 = new CountDownLatch(1);//负责发令枪响 比赛开始
        CountDownLatch latch2 = new CountDownLatch(5);//负责运动员比赛计数

        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            int no = i+1;
            System.out.println(no + "号运动员已经准备好,等待发令枪响...." );
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        latch1.await();
                        System.out.println(no + "号运动员完成比赛..." );
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        latch2.countDown();
                    }
                }
            };

            executorService.submit(runnable);
        }

        Thread.sleep(5000);
        latch1.countDown();
        System.out.println("5秒准备时间已过，发令枪响，比赛开始！");
        latch2.await();
        System.out.println("所有运动员已经完成比赛,老师可以下班了！");
        executorService.shutdown();
        
        
    }

        
        

        public static void main(String[] args) throws InterruptedException {
        test3();
        
    }
}
